package fxana;

import java.io.BufferedReader;
import java.io.FileReader;
import java.util.Date;
import java.util.Iterator;
import java.util.StringTokenizer;
import java.util.Vector;

import mathwork.Mathwork;

import org.jfree.chart.renderer.xy.CandlestickRenderer;
import org.jfree.data.xy.DefaultHighLowDataset;
import org.jfree.data.xy.OHLCDataset;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;

public class FxRawDataSet {
	private Vector<RawDataCell> RawDataBuffer=null;
	private String RawDataFile=null;	
	public static Integer DEFAULT_DAYNUMBER=5;
	public static Integer DEFAULT_DELTA_PERCENT=95;
	public FxRawDataSet(ParaFlag para){		
		RawDataBuffer=new Vector<RawDataCell>();		
		if(para.GetFilename()!=null){
			LoadRawData(para.GetFilename());
		}		
	}
	
	public FxRawDataSet(String filename){		
		RawDataBuffer=new Vector<RawDataCell>();		
		if(filename!=null){
			LoadRawData(filename);
		}		
	}
	
	public FxRawDataSet(){
		RawDataBuffer=new Vector<RawDataCell>();
		return;
	}
	
	public Vector <RawDataCell> GetRawDataBuffer(){
		return RawDataBuffer;
	}
	
	public boolean SetCompositeDataBuffer(Integer n){
		if(this.RawDataBuffer==null){
			return false;
		}
		
		if(n>=this.RawDataBuffer.size()){
			return false;
		}
		
		Vector<RawDataCell> tmp=this.GetCompositeDataBuffer(n);
		if(tmp==null){
			return false;
		}
		
		this.RawDataBuffer=tmp;
		return true;
		
	}
	
	public Vector<RawDataCell> GetCompositeDataBuffer(Integer n){
		if(n<=1)
			return this.RawDataBuffer;
		
		int i;
		Vector<RawDataCell> result=new Vector<RawDataCell>();
		for(i=0;i<this.RawDataBuffer.size();i+=n){
			Double open=this.RawDataBuffer.elementAt(i).GetStartValue();
			Double close;
			if(i+n>this.RawDataBuffer.size()){
				close=this.RawDataBuffer.elementAt(this.RawDataBuffer.size()-1).GetEndValue();
			}else{
				close=this.RawDataBuffer.elementAt(i+n-1).GetEndValue();
			}
			Double high=0.0;
			Double low=10000.0;
			int k;
			for(k=i;k<i+n;k++){
				if(k>this.RawDataBuffer.size()-1){
					break;
				}
				
				if(this.RawDataBuffer.elementAt(k).GetHighValue().compareTo(high)>=0){
					high=this.RawDataBuffer.elementAt(k).GetHighValue();
				}
				
				if(this.RawDataBuffer.elementAt(k).GetLowValue().compareTo(low)<=0){
					low=this.RawDataBuffer.elementAt(k).GetLowValue();
				}
			}
			
			result.add(new RawDataCell(this.RawDataBuffer.elementAt(i).GetFSRecDate(),open,
											high,
											low,
											close));
		}
		
		return result;
	}
	
	public Vector<Double> GetStartLists(){
		Vector <Double> result=new Vector <Double>();
		int i;
		for(i=0;i<RawDataBuffer.size();i++){
			result.add(RawDataBuffer.elementAt(i).GetStartValue());
		}
		
		return result;
	}
	
	public Vector<Double> GetHighLists(){
		Vector <Double> result=new Vector <Double>();
		int i;
		for(i=0;i<RawDataBuffer.size();i++){
			result.add(RawDataBuffer.elementAt(i).GetHighValue());
		}
		
		return result;
	}
	
	public Vector<Double> GetLowLists(){
		Vector <Double> result=new Vector <Double>();
		int i;
		for(i=0;i<RawDataBuffer.size();i++){
			result.add(RawDataBuffer.elementAt(i).GetLowValue());
		}
		
		return result;
	}
	
	public Vector<Double> GetEndLists(){
		Vector <Double> result=new Vector <Double>();
		int i;
		for(i=0;i<RawDataBuffer.size();i++){
			result.add(RawDataBuffer.elementAt(i).GetEndValue());
		}
		
		return result;
	}
	
	public RawDataCell GetLSMDataByIndex(Integer index,Integer daynumber){
		return GetLSMDataByIndex(index,daynumber,true);
	}
	
	public RawDataCell GetLSMDataByIndex(Integer index,Integer daynumber,boolean ifcheck){
		Double start;
		Double high;
		Double low;
		Double end;
		int i;
		
		Vector <Double> startlist=new Vector <Double>();
		Vector <Double> highlist=new Vector <Double>();
		Vector <Double> lowlist=new Vector <Double>();
		Vector <Double> endlist=new Vector <Double>();
		
		if(index-daynumber<=0 || index>RawDataBuffer.size()-1)
				return null;
		
		int count=0;
		for(i=index-1;count!=daynumber && i>=0;i--){
			startlist.add(RawDataBuffer.elementAt(i).GetStartValue());
			highlist.add(RawDataBuffer.elementAt(i).GetHighValue());
			lowlist.add(RawDataBuffer.elementAt(i).GetLowValue());
			endlist.add(RawDataBuffer.elementAt(i).GetEndValue());
			count++;
		}
		
		if(count<daynumber){
			return null;
		}
		
		start=RawDataBuffer.elementAt(index).GetStartValue();
		if(ifcheck){
			int ij;
			Double max=0.0;
			Double min=1000000.0;
			for(ij=0;ij<startlist.size();ij++){
				if(startlist.elementAt(ij).compareTo(max)>0){
					max=startlist.elementAt(ij);
				}
				if(startlist.elementAt(ij).compareTo(min)<0){
					min=startlist.elementAt(ij);
				}
			}
		
			if(start.compareTo(max)>0 || start.compareTo(min)<0){
				return null;
			}
		}
		
		high=Mathwork.lsm1(startlist, highlist,"High:"+daynumber.toString()).PolyValue(start);
		if(high.compareTo(start)<=0){
			//System.err.println("high ("+Mathwork.Roundup(high, 2)+") is strange and set to start ("+start+") "+RawDataBuffer.elementAt(index).GetFSRecDate());
			high=start;
		}
		
		low=Mathwork.lsm1(startlist, lowlist,"Low:"+daynumber.toString()).PolyValue(start);
		if(low.compareTo(start)>=0){
			//System.err.println("low ("+Mathwork.Roundup(low, 2)+") is strange and set to start ("+start+") "+RawDataBuffer.elementAt(index).GetFSRecDate());
			low=start;
		}
		
		end=Mathwork.lsm1(startlist, endlist,"End:"+daynumber.toString()).PolyValue(start);
		RawDataCell result=new RawDataCell(RawDataBuffer.elementAt(index).GetFSRecDate().toString(),
										start,
										high,
										low,
										end);
		
		return result;
	}
	public RawDataCell GetLSMDataByDate(Date date,Integer daynumber, boolean ifcheck){
		int index=-1;
		
		index=GetIndexByDate(date);
		if(index==-1){
			return null;
		}
		
		return this.GetLSMDataByIndex(index, daynumber,ifcheck);
	}
	
	public RawDataCell GetLSMDataByDate(Date date,Integer daynumber){
		return GetLSMDataByDate(date,daynumber, true);
	}
	
	public Vector<Double> GetPossibility(int numberofday,boolean ifweight,Integer percent){
		RawDataCell today=null;
		Vector<Double> mv;
		Double es_n2=null;
		Double es_n1=null;
		Double es_p1=null;
		Double es_p2=null;
		Double posb_n2=null;
		Double posb_n1=null;
		Double posb_p2=null;
		Double posb_p1=null;
		int ct_n2;
		int ct_n1;
		int ct_p1;
		int ct_p2;
		
		today=RawDataBuffer.lastElement();
		mv=this.GetdeltaByDate(today.GetRecDate(), numberofday,percent);
		
		es_n2=2*mv.elementAt(1);
		es_n1=mv.elementAt(1);
		es_p2=2*mv.elementAt(0);
		es_p1=mv.elementAt(0);
		
		ct_n2=ct_n1=ct_p2=ct_p1=0;
		Iterator<RawDataCell> it= RawDataBuffer.iterator();
		while(it.hasNext()){
			RawDataCell tmp=it.next();
			if(tmp.GetStartValue()-tmp.GetLowValue()>=es_n2){
				ct_n2++;				
			}
			
			if(tmp.GetStartValue()-tmp.GetLowValue()>=es_n1){
				ct_n1++;				
			}
			
			if(tmp.GetHighValue()-tmp.GetStartValue()>=es_p2){
				ct_p2++;
			}
			
			if(tmp.GetHighValue()-tmp.GetStartValue()>=es_p1){
				ct_p1++;
			}
			
		}
		
		posb_n2=(double) (ct_n2/RawDataBuffer.size());
		posb_n1=(double) (ct_n1/RawDataBuffer.size());
		posb_p1=(double) (ct_p1/RawDataBuffer.size());
		posb_p2=(double) (ct_p2/RawDataBuffer.size());
		
		Vector<Double> posb=new Vector<Double>();
		posb.add(0, posb_n2);
		posb.add(1, posb_n1);
		posb.add(2, posb_p1);
		posb.add(3, posb_p2);
		
		return posb;
	}

	public void Output(ParaFlag flag, int number){
		
		if(flag.IsSFlagSet()){
			return;
		}
		
		if(number > RawDataBuffer.size()){
			number=RawDataBuffer.size();
		}
		
		
		String spliter=" ";
		
		if(flag.IsCFlagSet()){
			spliter=",";
		}		
		
		/*title*/
		String title=null;
		title=String.format(RawDataCell.FMT_DATE, "Date")+spliter;
		
		if(flag.IsOFlagSet()) {
			title+=String.format(RawDataCell.FMT_DATA_STR, "Start")+spliter;
			title+=String.format(RawDataCell.FMT_DATA_STR, "High")+spliter;
			title+=String.format(RawDataCell.FMT_DATA_STR, "Low")+spliter;
			title+=String.format(RawDataCell.FMT_DATA_STR, "End")+spliter;
		}
		
		if(flag.IsAFlagSet()){
			title+=String.format(RawDataCell.FMT_DATA_STR, "AVG")+spliter;
		}
		
		Iterator<Integer> it=flag.GetMFlagIterator();
		
		while(it.hasNext()){
			Integer tmp=it.next();
			if(tmp==-1){
				tmp=FxRawDataSet.DEFAULT_DAYNUMBER;
			}
			title+=String.format(RawDataCell.FMT_DATA_STR, "MA("+tmp.toString()+")")+spliter;
		}
		
		it=flag.GetRFlagIterator();
		while(it.hasNext()){
			Integer tmp=it.next();
			title+=String.format(RawDataCell.FMT_DATA_STR, "MAR("+tmp.toString()+")")+spliter;
		}
		
		it=flag.GetEFlagIterator();
		while(it.hasNext()){
			Integer tmp=it.next();
			if(tmp==-1){
				tmp=FxRawDataSet.DEFAULT_DAYNUMBER;
			}
			title+=String.format(RawDataCell.FMT_DATA_STR, "E-2("+tmp.toString()+")")+spliter;
			title+=String.format(RawDataCell.FMT_DATA_STR, "E-1("+tmp.toString()+")")+spliter;
			title+=String.format(RawDataCell.FMT_DATA_STR, "E+1("+tmp.toString()+")")+spliter;
			title+=String.format(RawDataCell.FMT_DATA_STR, "E+2("+tmp.toString()+")")+spliter;
		}
		
		it=flag.GetDFlagIterator();
		while(it.hasNext()){
			Integer tmp=it.next();
			if(tmp==-1){
				tmp=FxRawDataSet.DEFAULT_DAYNUMBER;
			}
			Integer percent=FxRawDataSet.DEFAULT_DELTA_PERCENT;
			if(flag.IsZFlagSet()&&flag.GetZFlagIterator().hasNext()){
				percent=flag.GetZFlagIterator().next();
			}
			title+=String.format(RawDataCell.FMT_DATA_STR, "D-2a("+tmp.toString()+")")+spliter;
			title+=String.format(RawDataCell.FMT_DATA_STR, "D+2a("+tmp.toString()+")")+spliter;
			title+=String.format(RawDataCell.FMT_DATA_STR, "D-("+tmp.toString()+","+percent.toString()+")")+spliter;
			title+=String.format(RawDataCell.FMT_DATA_STR, "D+("+tmp.toString()+","+percent.toString()+")")+spliter;
		}
		
		it=flag.GetLFlagIterator();
		while(it.hasNext()){
			Integer tmp=it.next();
			if(tmp==-1){
				tmp=FxRawDataSet.DEFAULT_DAYNUMBER;
			}
			title+=String.format(RawDataCell.FMT_DATA_STR, "Start("+"Real"+")")+spliter;
			title+=String.format(RawDataCell.FMT_DATA_STR, "High("+tmp.toString()+")")+spliter;
			title+=String.format(RawDataCell.FMT_DATA_STR, "Low("+tmp.toString()+")")+spliter;
			title+=String.format(RawDataCell.FMT_DATA_STR, "End("+tmp.toString()+")")+spliter;
		}
		
		System.out.println(title);
		
		/*data*/		
		int index=RawDataBuffer.size()-number;
		while(index<RawDataBuffer.size()){
			RawDataCell tmp=RawDataBuffer.elementAt(index);
			index++;
			
			/*date*/
			String data=tmp.GetFSRecDate()+spliter;
			
			/*oflag*/
			if(flag.IsOFlagSet()) {
				data+=tmp.GetFSStartValue()+spliter;
				data+=tmp.GetFSHighValue()+spliter;
				data+=tmp.GetFSLowValue()+spliter;
				data+=tmp.GetFSEndValue()+spliter;				
			}
			
			/*aflag*/
			if(flag.IsAFlagSet()){
				data+=tmp.GetFSAverage()+spliter;
			}
			
			/*mflag*/
			it=flag.GetMFlagIterator();
			while(it.hasNext()){
				Integer numberofday=it.next();
				if(numberofday==-1){
					numberofday=FxRawDataSet.DEFAULT_DAYNUMBER;
				}
				Double mv= GetMovingAverageValueByDate(tmp.GetRecDate(), numberofday,flag.IFWeightMV());
				if(mv==null){
					data+=String.format(RawDataCell.FMT_DATA_STR,"N/A")+spliter;
				}else{
					data+=String.format(RawDataCell.FMT_DATA, mv)+spliter;
				}
			}
			
			/*rflag*/
			it=flag.GetRFlagIterator();
			while(it.hasNext()){
				Integer numberofday=it.next();
				if(numberofday==-1){
					numberofday=FxRawDataSet.DEFAULT_DAYNUMBER;
				}
				Double mvr=GetMovingAverageRateByDate(tmp.GetRecDate(), numberofday,flag.IFWeightMV());
				if(mvr==null){
					data+=String.format(RawDataCell.FMT_DATA_STR, "N/A" )+spliter;
				}else{
					data+=String.format(RawDataCell.FMT_DATA, mvr )+spliter;				
				}
			}
			
			/*eflag*/
			it=flag.GetEFlagIterator();
			while(it.hasNext()){
				Integer numberofday=it.next();
				if(numberofday==-1){
					numberofday=FxRawDataSet.DEFAULT_DAYNUMBER;
				}
				Double mv=GetMovingAverageValueByDate(tmp.GetRecDate(), numberofday,flag.IFWeightMV());
				if(mv==null){
					data+=String.format(RawDataCell.FMT_DATA_STR, "N/A")+spliter;
					data+=String.format(RawDataCell.FMT_DATA_STR, "N/A")+spliter;
					data+=String.format(RawDataCell.FMT_DATA_STR, "N/A")+spliter;
					data+=String.format(RawDataCell.FMT_DATA_STR, "N/A")+spliter;
				}else{
					data+=String.format(RawDataCell.FMT_DATA, mv*(1-0.02))+spliter;
					data+=String.format(RawDataCell.FMT_DATA, mv*(1-0.01))+spliter;
					//data+=String.format(RawDataCell.FMT_DATA, mv*(1-0.005))+spliter;
					//data+=String.format(RawDataCell.FMT_DATA, mv*(1+0.005))+spliter;
					data+=String.format(RawDataCell.FMT_DATA, mv*(1+0.01))+spliter;
					data+=String.format(RawDataCell.FMT_DATA, mv*(1+0.02))+spliter;
				}
			}
			
			/*dflag*/
			it=flag.GetDFlagIterator();
			while(it.hasNext()){
				Integer numberofday=it.next();
				if(numberofday==-1){
					numberofday=FxRawDataSet.DEFAULT_DAYNUMBER;
				}
				Double mv=tmp.GetStartValue();
				Integer percent=FxRawDataSet.DEFAULT_DELTA_PERCENT;
				if(flag.IsZFlagSet()){
					Iterator<Integer> itz=flag.GetZFlagIterator();
					percent=itz.next();
				}
				
				Vector<Double> delta=GetdeltaByDate(tmp.GetRecDate(), numberofday,percent);
				if(delta==null){
					data+=String.format(RawDataCell.FMT_DATA_STR, "N/A")+spliter;
					data+=String.format(RawDataCell.FMT_DATA_STR, "N/A")+spliter;
					data+=String.format(RawDataCell.FMT_DATA_STR, "N/A")+spliter;
					data+=String.format(RawDataCell.FMT_DATA_STR, "N/A")+spliter;
				}else{
					data+=String.format(RawDataCell.FMT_DATA, mv-delta.elementAt(1))+spliter;
					data+=String.format(RawDataCell.FMT_DATA, mv+delta.elementAt(0))+spliter;
					data+=String.format(RawDataCell.FMT_DATA, delta.elementAt(1))+spliter;
					data+=String.format(RawDataCell.FMT_DATA, delta.elementAt(0))+spliter;
				}
			}
			
			/*lflag*/
			it=flag.GetLFlagIterator();
			while(it.hasNext()){
				Integer numberofday=it.next();
				if(numberofday==-1){
					numberofday=FxRawDataSet.DEFAULT_DAYNUMBER;
				}
				RawDataCell estval=this.GetLSMDataByDate(tmp.GetRecDate(), numberofday);
				if(estval==null){
					data+=String.format(RawDataCell.FMT_DATA_STR, "N/A")+spliter;
					data+=String.format(RawDataCell.FMT_DATA_STR, "N/A")+spliter;
					data+=String.format(RawDataCell.FMT_DATA_STR, "N/A")+spliter;
					data+=String.format(RawDataCell.FMT_DATA_STR, "N/A")+spliter;
				}else{
					data+=String.format(RawDataCell.FMT_DATA, estval.GetStartValue())+spliter;
					data+=String.format(RawDataCell.FMT_DATA, estval.GetHighValue())+spliter;
					data+=String.format(RawDataCell.FMT_DATA, estval.GetLowValue())+spliter;
					data+=String.format(RawDataCell.FMT_DATA, estval.GetEndValue())+spliter;
				}
			}
			
			System.out.println(data);
		}
		System.out.println(title);
	}
	
	public boolean LoadRawData(String filename){
		String aLine=null;		
		
		if(filename==null){
			System.err.println("Data file is not specified!");
			return false;
		}
		
		if(RawDataFile!=null){
			/*Remove the old data*/
			RawDataBuffer.clear();
		}
		/*Set the file name*/
		RawDataFile=filename;		
		
		try{
			BufferedReader fin=new BufferedReader(new FileReader(RawDataFile));
			while((aLine=fin.readLine())!=null){
				StringTokenizer tokenLine= new StringTokenizer(aLine,",");
				String date=new String(tokenLine.nextToken());				
				Double  startv=new Double(tokenLine.nextToken());
				Double  highv=new Double(tokenLine.nextToken());
				Double  lowv=new Double(tokenLine.nextToken());
				Double  endv=new Double(tokenLine.nextToken());
				RawDataCell newcell= new RawDataCell(date,startv,highv,lowv,endv);
				if(newcell.IsDataOK()){
					RawDataBuffer.add(newcell);
				}else{
					System.err.print("Wrong data:"+newcell.GetRecDate()+"\n");
					return false;
				}
			}
			fin.close();
		}catch(Exception e){			
			//System.err.println(e.getMessage());
			return false;			
		}		
		return true;
	}	
	
	public RawDataCell GetDataByIndex(int index){
		return RawDataBuffer.elementAt(index);
	}
	
	public RawDataCell GetDataByDate(Date date){
		return RawDataBuffer.elementAt(GetIndexByDate(date));
	}
	
	public int GetIndexByDate(Date date){
		
		int index=-1;
		
		Iterator<RawDataCell> it=RawDataBuffer.iterator();
		while(it.hasNext()){
			RawDataCell tmp=it.next();
			if(tmp.GetRecDate().compareTo(date)==0){
				/*the index of the specified date found*/
				index=RawDataBuffer.indexOf(tmp);
				break;
			}			
		}
		
		return index;
	}
	
	
	public Vector<Double> GetdeltaByIndex(Integer index, Integer numberofday,Integer percent){
		Vector<Double> result=new Vector<Double>();
		
		if( index<=0 ||  numberofday <20 || index-numberofday<0 )
			return null;
		
		int loop;
		Vector<Double>hs=new Vector<Double>();
		Vector<Double>sl=new Vector<Double>();
		
		for(loop=index-1; index - loop <= numberofday ; loop--){
				RawDataCell tmp=RawDataBuffer.elementAt(loop);
				hs.add(tmp.GetHighStart());
				sl.add(tmp.GetStartLow());
		}
		
		result.add(Mathwork.lognormalest(hs, percent/100.0).elementAt(0));
		result.add(Mathwork.lognormalest(sl, percent/100.0).elementAt(0));
		
		return result;
	}
	
	public Vector<Double> GetdeltaByDate(Date date, Integer numberofday,Integer percent){
		int index=-1;
		
		index=GetIndexByDate(date);
		if(index==-1){
			return null;
		}
		
		return GetdeltaByIndex(index,numberofday,percent);
		
	}
	
	/*Calculate MA on 'numberofday' from index-1 */
	public Double GetMovingAverageValueByIndex(Integer index, Integer numberofday, boolean ifweight){
		Double tmpv=0.0;		
		Double Weight=new Double(numberofday);
		
		
		if( index<=0 ||  numberofday <=0 || index-numberofday<0 )
			return null;
		
		int loop;
		for(loop=index-1; index - loop <= numberofday ; loop--){
				RawDataCell tmp=RawDataBuffer.elementAt(loop);
				if(ifweight==true){
					tmpv+=tmp.GetAverage()*Weight;
					Weight--;
				}else{
					tmpv+=tmp.GetAverage();
				}
		}
		
		if(ifweight==true){
			tmpv/=new Double((numberofday+1)*numberofday/2);
		}else{
			tmpv/=new Double(numberofday);
		}
			
		return tmpv;
		
	}
	
	public Double GetMovingAverageValueByDate(Date date, Integer numberofday, boolean ifweight){
		int index=-1;
		
		index=GetIndexByDate(date);
		if(index==-1){
			return null;
		}
		
		return GetMovingAverageValueByIndex(index,numberofday,ifweight);
		
	}
		
	public Double GetMovingAverageRateByIndex(Integer index, Integer numberofday,boolean ifweight){
		Double rate=0.0;
		Double mav=0.0;
		Double startvalue=0.0;		
				
		startvalue=RawDataBuffer.elementAt(index).GetStartValue();
		mav=GetMovingAverageValueByIndex(index,numberofday,ifweight);
		
		if(mav==null)
			return null;
			
		rate=(startvalue - mav)/mav;		
		return rate;
	}
	
	public Double GetMovingAverageRateByDate(Date date, Integer numberofday,boolean ifweight){
		int index=-1;
		
		index=GetIndexByDate(date);
		if(index==-1){
			return null;
		}
		
		return GetMovingAverageRateByIndex(index,numberofday,ifweight);
		
	}

	public Double GetMinValueByIndex(Integer index,Integer numberofday){
		
		if(numberofday <=0 || index-numberofday<0)
			return null;
		
		int count=numberofday;
		int i=index-1;
		Double min=10000.0;
		do{
			if(min.compareTo(this.RawDataBuffer.elementAt(i).GetLowValue())>=0)
				min=Mathwork.Roundup(this.RawDataBuffer.elementAt(i).GetLowValue(), 2);
		}while(--count>0);
		return min;
	}
	
	public Double GetMinValueByDate(Date date,Integer numberofday){
		return this.GetMinValueByIndex(this.GetIndexByDate(date), numberofday);
	}
	
public Double GetMaxValueByIndex(Integer index,Integer numberofday){
		
		if(numberofday <=0 || index-numberofday<0)
			return null;
		
		int count=numberofday;
		int i=index-1;
		Double max=0.0;
		do{
			if(max.compareTo(this.RawDataBuffer.elementAt(i).GetHighValue())<=0)
				max=Mathwork.Roundup(this.RawDataBuffer.elementAt(i).GetHighValue(), 2);
		}while(--count>0);
		return max;
	}
	
	public Double GetMaxValueByDate(Date date,Integer numberofday){
		return this.GetMaxValueByIndex(this.GetIndexByDate(date), numberofday);
	}
	
	
	public void PlotData(ParaFlag flag,int number,String SavePNGFileName) throws InterruptedException{
		FxPlot fxplot=new FxPlot();		
		
		if(RawDataBuffer==null){
			return;
		}
		
		if(number > RawDataBuffer.size()){
			number=RawDataBuffer.size();
		}
		
		if(flag.IsOFlagSet()){
			/* CandlestickChart */
			Date[] date=new Date[number];
			double[] start=new double[number];
			double[] high=new double[number];
			double[] low=new double[number];
			double[] end=new double[number];
			double[] volume=new double[number];

			int i,j;
			for(j=0,i=RawDataBuffer.size()-number;j<number;i++,j++){
				RawDataCell tmp=RawDataBuffer.elementAt(i);
				date[j]=tmp.GetRecDate();
				start[j]=tmp.GetStartValue().doubleValue();
				high[j]=tmp.GetHighValue().doubleValue();
				low[j]=tmp.GetLowValue().doubleValue();
				end[j]=tmp.GetEndValue().doubleValue();			
				volume[j] =0; 
			}
			OHLCDataset dataset= new DefaultHighLowDataset("CandleStick",date,high,low,start,end,volume);
			CandlestickRenderer renderer=FxPlot.GetCandlestkRendterer();
			fxplot.SetPlot(dataset, renderer);
		}
		
		if(flag.IsAFlagSet()){
			XYSeries AVRSeries = new XYSeries("AVR");
			int i1,j1;
			for(j1=0,i1=RawDataBuffer.size()-number;j1<number;i1++,j1++){
				RawDataCell tmp=RawDataBuffer.elementAt(i1);
				Date date=tmp.GetRecDate();
				AVRSeries.add(date.getTime(), tmp.GetAverage());
			}
			XYSeriesCollection dataset = new XYSeriesCollection();
			dataset.addSeries(AVRSeries);
			fxplot.SetPlot(dataset, FxPlot.GetStandardXYItemRenderer());
		}
		
		if(flag.IsMFlagSet()){
			Iterator<Integer> it=flag.GetMFlagIterator();
			while(it.hasNext()){
				Integer numberofday=it.next();
				if(numberofday==-1){
					numberofday=FxRawDataSet.DEFAULT_DAYNUMBER;
				}
				XYSeries s1 = new XYSeries("M("+Integer.toString(numberofday)+")");
								
				int i1,j1;
				for(j1=0,i1=RawDataBuffer.size()-number;j1<number;i1++,j1++){
					RawDataCell tmp=RawDataBuffer.elementAt(i1);
					Date date1=tmp.GetRecDate();
					Double value=GetMovingAverageValueByDate(date1, numberofday,flag.IFWeightMV());
					if(value!=null)
						s1.add(date1.getTime(),value.doubleValue());
				}
				
				XYSeriesCollection dataset = new XYSeriesCollection();
				dataset.addSeries(s1);
				fxplot.SetPlot(dataset, FxPlot.GetStandardXYItemRenderer());
			}
		}
		
		
		if(flag.IsEFlagSet()){
			Iterator<Integer> it=flag.GetEFlagIterator();
			while(it.hasNext()){
				Integer numberofday=it.next();
				if(numberofday==-1){
					numberofday=FxRawDataSet.DEFAULT_DAYNUMBER;
				}
				XYSeries s1 = new XYSeries("E-2("+Integer.toString(numberofday)+")");
				XYSeries s2 = new XYSeries("E-1("+Integer.toString(numberofday)+")");
				XYSeries s3 = new XYSeries("E+1("+Integer.toString(numberofday)+")");
				XYSeries s4 = new XYSeries("E+2("+Integer.toString(numberofday)+")");
				
				int i1,j1;
				for(j1=0,i1=RawDataBuffer.size()-number;j1<number;i1++,j1++){
					RawDataCell tmp=RawDataBuffer.elementAt(i1);
					Date date1=tmp.GetRecDate();
					Double FMV=GetMovingAverageValueByDate(date1, numberofday,flag.IFWeightMV());
					if(FMV!=null){
						double value=FMV.doubleValue();
						s1.add(date1.getTime(),value*(1-0.02));
						s2.add(date1.getTime(),value*(1-0.01));
						s3.add(date1.getTime(),value*(1+0.01));
						s4.add(date1.getTime(),value*(1+0.02));
					}
				}
				
				XYSeriesCollection dataset = new XYSeriesCollection();
				dataset.addSeries(s1);
				dataset.addSeries(s2);
				dataset.addSeries(s3);
				dataset.addSeries(s4);
				fxplot.SetPlot(dataset, FxPlot.GetStandardXYItemRenderer());
			}
		}
		
		if(flag.IsDFlagSet()){
			Iterator<Integer> it=flag.GetDFlagIterator();
			while(it.hasNext()){
				Integer numberofday=it.next();
				if(numberofday==-1){
					numberofday=FxRawDataSet.DEFAULT_DAYNUMBER;
				}
				XYSeries s1 = new XYSeries("D-1a("+Integer.toString(numberofday)+")");
				XYSeries s2 = new XYSeries("D+1a("+Integer.toString(numberofday)+")");
				
				int i1,j1;
				for(j1=0,i1=RawDataBuffer.size()-number;j1<number;i1++,j1++){
					RawDataCell tmp=RawDataBuffer.elementAt(i1);
					Date date1=tmp.GetRecDate();
					Integer percent=FxRawDataSet.DEFAULT_DELTA_PERCENT; 
					if(flag.IsZFlagSet()){
						Iterator<Integer> itz=flag.GetZFlagIterator();
						percent=itz.next();
					}
					
					Vector<Double> delta=GetdeltaByDate(date1, numberofday,percent);
					if(delta!=null){
						double value=tmp.GetStartValue();
						s1.add(date1.getTime(),value-delta.elementAt(1).doubleValue());
						s2.add(date1.getTime(),value+delta.elementAt(0).doubleValue());
					}
				}
				
				XYSeriesCollection dataset = new XYSeriesCollection();
				dataset.addSeries(s1);
				dataset.addSeries(s2);
				fxplot.SetPlot(dataset, FxPlot.GetStandardXYItemRenderer());
			}
		}
		
		if(flag.IsLFlagSet()){
			Iterator<Integer> it=flag.GetLFlagIterator();
			while(it.hasNext()){
				Integer numberofday=it.next();
				if(numberofday==-1){
					numberofday=FxRawDataSet.DEFAULT_DAYNUMBER;
				}
				XYSeries s1 = new XYSeries("Start("+"Real"+")");
				XYSeries s2 = new XYSeries("High("+Integer.toString(numberofday)+")");
				XYSeries s3 = new XYSeries("Low("+Integer.toString(numberofday)+")");
				XYSeries s4 = new XYSeries("End("+Integer.toString(numberofday)+")");
				
				int i1,j1;
				for(j1=0,i1=RawDataBuffer.size()-number;j1<number;i1++,j1++){
					RawDataCell tmp=RawDataBuffer.elementAt(i1);
					Date date1=tmp.GetRecDate();
					RawDataCell estval=this.GetLSMDataByDate(date1, numberofday);
					if(estval!=null){
						s1.add(date1.getTime(),estval.GetStartValue());
						s2.add(date1.getTime(),estval.GetHighValue());
						s3.add(date1.getTime(),estval.GetLowValue());
						s4.add(date1.getTime(),estval.GetEndValue());
					}
				}
				
				XYSeriesCollection dataset = new XYSeriesCollection();
				dataset.addSeries(s1);
				dataset.addSeries(s2);
				dataset.addSeries(s3);
				dataset.addSeries(s4);
				fxplot.SetPlot(dataset, FxPlot.GetStandardXYItemRenderer());
			}
		}
		
		int i1,j1;
		Double max =0.0;
		Double min =10000.0;
		for(j1=0,i1=RawDataBuffer.size()-number;j1<number;i1++,j1++){
			RawDataCell tmp=RawDataBuffer.elementAt(i1);
			if(tmp.GetHighValue().compareTo(max)>0)
				max=tmp.GetHighValue();
			
			if(tmp.GetLowValue().compareTo(min)<0)
				min=tmp.GetLowValue();		
		}
		
		fxplot.SetPlotAxisRangeY(min-2.0, max+2.0);
		

		String start=RawDataBuffer.elementAt(RawDataBuffer.size()-number).GetFSRecDate();
		String end=RawDataBuffer.elementAt(RawDataBuffer.size()-1).GetFSRecDate();
		fxplot.SetPlotTitle(start+"-  "+end);
		
		
		if(number>60){
			fxplot.SetPlotTickunitX(10);
		}else if(number >10){
			fxplot.SetPlotTickunitX(5);
		}else{
			fxplot.SetPlotTickunitX(1);
		}
		
		/*fxplot.Show();*/
		Thread tplot=new Thread(fxplot);
		tplot.run();
		
		Thread.sleep(1000);
		if(SavePNGFileName!=null){
			fxplot.SavePlotAsPNG(SavePNGFileName, 1024, 768);
		}
	}
	
}
